//核心模块
const gulp = require('gulp') //核心
const minimist = require('minimist') //命令行传递参数
const options = minimist(process.argv.slice(2))
  ? minimist(process.argv.slice(2))
  : '' //命令行传递参数 options   gulp xxxx ----xxx  ----xxx就是传参方式

const mkdirp = require('mkdirp') //创建文件任务
const browserSync = require('browser-sync').create() //创建一个browserSync实例
const babel = require('gulp-babel') //es6转es5
const autoprefixer = require('gulp-autoprefixer') //css自动前缀
const sass = require('gulp-sass') //sass转换工具
const browserify = require('gulp-browserify'); // 自动处理模块依赖
var ts = require('gulp-typescript') //typescript

//打包
const gulpSequence = require('gulp-sequence') //队列执行任务插件
const clean = require('gulp-clean') //删除文件夹插件
const htmlmin = require('gulp-htmlmin');
const minicss = require("gulp-minify-css");			//CSS压缩
const uglify = require("gulp-uglify");				//JS压缩
const rev = require('gulp-rev') //添加md5后缀
const revCollector = require('gulp-rev-collector');		//替换文件路径

//ty配置
const tsConfig = ts.createProject('./tsconfig.json') //typescript配置文件

/****************目录常量配置*********************/
const files = {
  main: options['fileName'] ? options['fileName'] : '' + './src/',
  outPut: './dist/',
  src: {
    //源文件目录结构 也可以用于创建目录
    html: 'html/', //html源文件目录
    css: 'css/', //css源文件目录
    scss: 'scss/', //scss源文件目录
    lib: 'lib/', //第三方源文件目录
    js: 'js/', //JS源文件目录(es6)
    es6: 'es6/', //JS源文件目录(es5) 不能改动 改动只能去es6改 因为这里是转译的文件
    images: 'images/', //图片源文件目录
    font: 'font/', //字体源文件目录
    comp: 'comp/', //组件源文件目录
    media: 'media/', //媒体源文件目录
    ts: 'ts/' //媒体源文件目录
  },
  dist: {
    //生产环境目录
    html: 'html/',
    css: 'css/',
    scss: 'scss/',
    lib: 'lib/',
    js: 'js/',
    es6: 'es6/',
    images: 'images/',
    font: 'font/',
    comp: 'comp/',
    media: 'media/'
  },
  rev: {}
}

function swallowError(error) {
  // If you want details of the error in the console
  console.error(error.toString())

  this.emit('end')
}

/****************子任务：创建文件夹文件夹*********************/
gulp.task('createFile', () => {
  let oName = options['fileName'] ? options['fileName'] + '/' : 'src/'

  if (oName) {
    if (typeof oName !== 'string') {
      console.log('项目文件夹名称，只能是字符串')
      return
    }
  }

  mkdirp.sync(oName)
  for (let i in files['src']) {
    mkdirp.sync(oName + files['src'][i])
  }
})
/****************************end*****************************/

/****************子任务：使用Browsersync  同步刷新************/
const reload = browserSync.reload

gulp.task('browserSync', function () {
  if (options['fileName']) {
    console.log(options['fileName'])
    if (typeof options['fileName'] !== 'string') {
      console.log('项目文件夹名称，只能是字符串')
      return
    }
  }

  browserSync.init({
    port: 8999,
    server: {
      baseDir: files['main']
    }
  })
})
/****************************end*****************************/

/****************子任务：编译ts并且转换为js*********************/
gulp.task('tsc', function () {
  gulp
    .src(files['main'] + files['src']['ts'] + '**/*.ts')
    .pipe(tsConfig())
    .on('error', swallowError)
    .pipe(gulp.dest(files['main'] + files['src']['js']))
})
/****************************end*****************************/

/****************子任务：es6转es5  同步刷新************/
gulp.task('babeljs', function () {
  return gulp
    .src(files['main'] + files['src']['es6'] + '**/*.js')
    .pipe(babel({
      "presets": ["es2015", "es2016", "es2017"],
      "plugins": [
        ["transform-runtime", {
          "helpers": false,
          "polyfill": false,
          "regenerator": true,
          "moduleName": "babel-runtime"
        }]
      ]
      //将es7转换es5
    }))
    .on('error', swallowError)
    .pipe(browserify())
    .pipe(gulp.dest(files['main'] + files['src']['js']))
})
/****************************end*****************************/

/****************子任务：转变scss到css*********************/
gulp.task('scss', function () {
  gulp
    .src(files['main'] + files['src']['scss'] + '**/*.scss')
    .pipe(sass())
    .on('error', swallowError)
    //自动添加前缀
    .pipe(
      //  因为postCss版本更新，之前版本的配置已无效 browsers ({}) 改为 overrideBrowserslist 不然会为报错 虽然这个报错不会有啥影响
      autoprefixer({
        overrideBrowserslist: [
          'last 2 versions',
          'Android >= 4.0',
          'iOS 7',
          'last 3 Safari versions'
        ],
        cascade: true, //是否美化属性值 默认：true 像这样：
        //-webkit-transform: rotate(45deg);
        //        transform: rotate(45deg);
        remove: false //是否去掉不必要的前缀 默认：true
      })
    )
    .pipe(gulp.dest(files['main'] + files['src']['css']))
})
/****************************end*****************************/


/****************子任务：清空文件夹*********************/
gulp.task('clean', function (e) {
  let cleanFileName = ['dist', 'rev']
  return gulp
    .src(cleanFileName, { read: false }) //清空dist和rev文件夹
    .pipe(clean())
})
/****************************end*****************************/

/****************子任务：压缩CSS,添加MD5后缀，并生成json对应文件************/
gulp.task('pro_css', function () {
  let srcLocation = files['main'] + files['src']['css'] + '**/*.css'
  return gulp
    .src(srcLocation)
    .pipe(minicss())			//进行压缩
    .pipe(rev())
    .pipe(gulp.dest(files['outPut'] + 'css'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('./rev/css'))
})
/****************************end*****************************/


/****************子任务：压缩JS，添加MD5后缀，并生成json对应文件************/
gulp.task('pro_js', function () {
  let srcLocation = files['main'] + files['src']['js'] + '**/*.js'

  return gulp
    .src(srcLocation)
    .pipe(uglify()) //进行压缩
    .pipe(rev())
    .pipe(gulp.dest(files['outPut'] + 'js'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('./rev/js'))
})
/****************************end*****************************/

/****************子任务: 压缩html(压缩页面javascript、css，去除页面空格、注释，删除多余属性等操作)************/
gulp.task('pro_htmlmin', function () {
  let srcLocation = files['main'] + files['src']['html'] + '**/*.html'

  let options = {
    removeComments: true,//清除HTML注释
    collapseWhitespace: true,//压缩HTML
    collapseBooleanAttributes: true,//省略布尔属性的值 <input checked="true"/> ==> <input />
    removeEmptyAttributes: true,//删除所有空格作属性值 <input id="" /> ==> <input />
    removeScriptTypeAttributes: true,//删除<script>的type="text/javascript"
    removeStyleLinkTypeAttributes: true,//删除<style>和<link>的type="text/css"
    minifyJS: true,//压缩页面JS
    minifyCSS: true//压缩页面CSS
  };

  gulp.src(srcLocation)
    .pipe(htmlmin(options))
    .pipe(gulp.dest(files['outPut'] + 'html'))
});
/****************************end*****************************/


/****************子任务：替换文件路径************/
gulp.task('pro_rev', function () {
  let srcLocation = ['./rev/' + '**/*.json', files['main'] + '**/*.html'];

  return gulp.src(srcLocation)
    .pipe(revCollector({				//根据json文件进行资源路径替换
      replaceReved: true,
      dirReplacements: {				//配置要替换的文件夹路径
        'css/': 'css/',
        'js/': 'js/',
        'images/': 'images/'
      }
    }))
    .pipe(gulp.dest(files['outPut']));	//生成到目标HTML目录
})
/****************************end*****************************/

/****************总任务：一键用于开发环境************/
gulp.task('dev', ['browserSync'], function () {
  //监听files['main'] 任何文件变化,实时刷新
  for (let i in files['src']) {
    // main/src/xxx/xxxx.xxx
    if (i !== 'js' && i !== 'scss' && i !== 'ts') {
      gulp
        .watch(files['main'] + files['src'][i] + '**/*.' + i)
        .on('change', reload)
    } else {
      //js和scss因为需要转译 所以另行处理
      if (i === 'js') {
        gulp
          .watch(files['main'] + files['src']['es6'] + '**/*.js', ['babeljs'])
          .on('change', reload)
      }
      if (i === 'scss') {
        gulp
          .watch(files['main'] + files['src']['scss'] + '**/*.scss', ['scss'])
          .on('change', reload)
      }

      if (i === 'ts') {
        gulp
          .watch(files['main'] + files['src']['ts'] + '**/*.ts', ['tsc'])
          .on('change', reload)
      }
    }
  }
})


// "pro_img", "copy",

gulp.task('pro', gulpSequence("clean", "pro_htmlmin", "scss", "pro_css", "pro_js", "pro_rev"));

/**
 * --fileName 是属性名 main是参数  可以传多个
 * gulp dev --fileName main
 *
 */
